package com.leiyuee.springbase;

import com.leiyuee.springbase.service.UserService;
import lombok.experimental.Accessors;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@Accessors()
public class Test {

    public static void main(String[] args) throws Exception {
        //new一个sprng容器,去扫描 AppConfig.class配置的扫描路径,通过路径找到里面的bean对象
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        //bean对象
        UserService userService = (UserService)applicationContext.getBean("userService");//Map<BeanName,Bean对象>--多次根据name找会是同一个
        userService.test();

        //放入单例池,就叫做bean对象,通过getBean拿到
        // Object o = new Object();
        // applicationContext.getBeanFactory().registerSingleton("aaa",o);


        // XXX: UserService userService1 = new UserService();
        //FIXME
        //获取对象的所有的属性  判断是否有Autowired 如何就赋值  --> todo:1.1 依赖注入
        // for (Field field:userService1.getClass().getDeclaredFields()){
        //     if (field.isAnnotationPresent(Autowired.class)){
        //         field.set(userService1,??);
        //     }
        // }

    }

    //TODO:1. bean的生命周期
    /**
     *  ***.class -->推断无参构造方法-->普通对象-->`依赖注入`-->afterPropertiesSet -->初始化后(AOP)-->代理对象--> 放入单例池Map<BeanName,Bean对象>
     *            --spring都能做这些
     *
     * bean的实例化:就是通过构造方法得到一个对象  -->JVM层面的初始化
     * bean的初始化 --> 执行afterPropertiesSet
     * 单例bean --> 当前JVM下的一个名字
     * 推断构造方法: 找的时候 先byType 如果有多个就会 再byName (Autowired注解) 找到对应的对象
     *
     * AOP:生成代理对象, 然后代理对象中 生成一个  target 对象(切换对象),将普通对象赋值给teraet对象,
     *  class xxxServiceProxy extends xxxService{
     *      xxxService target;
     *      public void test(){
     *          //先执行切面逻辑
     *          target.test();//不是 super.test();  xxxService普通对象.test 是通过依赖注入赋值之后了的,其属性是有值的 -->就是动态代理
     *      }
     *  }
     *
     *
     */


   /* protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }

        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try {
            this.populateBean(beanName, mbd, instanceWrapper);
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }
*/
}
